Skip to content

Conversation

@Sysix
Copy link
Member

@Sysix Sysix commented Nov 25, 2025

Adds createWorkspace and destroyWorkspace for handling multiple "cwd" at the same time.
This concept of workspace is later used for the language server for starting / stopping the ServerLinter for a workspace.

I would much prefer something like createWorkspace(rootDir:string): { lintFile(), loadPlugin() }, but I am not sure if this is really possible with napi. Added instead for every function one extra parameter to define the workspace.
At the moment, only plugins and rules are stored for each workspace separately.

You can see in the downstream PR how the concept is used when starting / restarting a workspace :)

@github-actions github-actions bot added A-linter Area - Linter A-cli Area - CLI A-editor Area - Editor and Language Server A-linter-plugins Area - Linter JS plugins labels Nov 25, 2025
Copy link
Member Author

Sysix commented Nov 25, 2025


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions github-actions bot added the C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior label Nov 25, 2025
@codspeed-hq
Copy link

codspeed-hq bot commented Nov 25, 2025

CodSpeed Performance Report

Merging #16121 will not alter performance

Comparing 11-25-chore_oxlint_napi_add_createworkspace_destroyworkspace_js_callback_function (8a4ded6) with main (9097167)1

Summary

✅ 42 untouched
⏩ 3 skipped2

Footnotes

  1. No successful run was found on main (d3a34f8) during the generation of this report, so 9097167 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

  2. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@Sysix Sysix force-pushed the 11-25-chore_oxlint_napi_add_createworkspace_destroyworkspace_js_callback_function branch from cc187d9 to 4a61876 Compare November 25, 2025 19:21
@Sysix Sysix changed the base branch from copilot/add-clear-loaded-plugin-function to graphite-base/16121 November 26, 2025 19:26
@Sysix Sysix force-pushed the 11-25-chore_oxlint_napi_add_createworkspace_destroyworkspace_js_callback_function branch from 4a61876 to d05b90b Compare November 26, 2025 19:26
@Sysix Sysix force-pushed the graphite-base/16121 branch from bf3b963 to 9c10d86 Compare November 26, 2025 19:26
@Sysix Sysix changed the base branch from graphite-base/16121 to main November 26, 2025 19:26
@Sysix Sysix force-pushed the 11-25-chore_oxlint_napi_add_createworkspace_destroyworkspace_js_callback_function branch 4 times, most recently from 1f793f4 to fda5042 Compare November 27, 2025 15:52
@Sysix Sysix requested a review from Copilot November 27, 2025 15:53
Copilot finished reviewing on behalf of Sysix November 27, 2025 15:57
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds workspace management capabilities to the oxlint NAPI interface by introducing createWorkspace and destroyWorkspace JavaScript callback functions. The changes enable isolated workspaces for linting plugins, where each workspace maintains its own set of loaded plugins and rules based on a workspace root directory. This involves threading the workspace directory (cwd) as a parameter throughout the Rust and TypeScript codebases.

Key changes:

  • Added createWorkspace and destroyWorkspace callback types and implementations to manage workspace lifecycle
  • Modified Linter struct to include a cwd field and updated all instantiation sites
  • Extended ConfigStoreBuilder::from_oxlintrc to accept a cwd parameter for workspace-aware plugin loading
  • Converted registeredPluginUrls and registeredRules from simple data structures to Maps keyed by workspace directory

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
tasks/benchmark/benches/linter.rs Added empty string as cwd parameter to Linter::new call
napi/playground/src/lib.rs Added dummy /root path parameters for ConfigStoreBuilder::from_oxlintrc and Linter::new
crates/oxc_linter/src/tester.rs Added /root path parameters to test linter initialization
crates/oxc_linter/src/lib.rs Added cwd field to Linter struct and updated constructor signature
crates/oxc_linter/src/external_linter.rs Added CreateWorkspaceCb and DestroyWorkspaceCb types, updated ExternalLinter struct
crates/oxc_linter/src/config/config_builder.rs Added cwd parameter to from_oxlintrc and plugin loading functions
crates/oxc_language_server/src/linter/server_linter.rs Updated linter initialization to pass root path as cwd
crates/oxc_language_server/src/linter/isolated_lint_handler.rs Added cwd parameter to handler initialization
apps/oxlint/src/run.rs Added JsCreateWorkspaceCb and JsDestroyWorkspaceCb type definitions, updated lint function signature
apps/oxlint/src/lint.rs Integrated workspace creation in CliRunner::new, threaded cwd through configuration
apps/oxlint/src/js_plugins/external_linter.rs Implemented wrapper functions for workspace creation/destruction callbacks
apps/oxlint/src-js/plugins/workspace.ts New file implementing workspace management with create/destroy functions
apps/oxlint/src-js/plugins/load.ts Modified plugin loading to be workspace-aware using Maps instead of Sets
apps/oxlint/src-js/plugins/lint.ts Updated linting to retrieve rules per workspace directory
apps/oxlint/src-js/plugins/index.ts Exported workspace management functions
apps/oxlint/src-js/cli.ts Added wrapper functions and integrated workspace callbacks into CLI
apps/oxlint/src-js/bindings.d.ts Added TypeScript type definitions for workspace callbacks

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Sysix Sysix force-pushed the 11-25-chore_oxlint_napi_add_createworkspace_destroyworkspace_js_callback_function branch from fda5042 to ce53742 Compare November 27, 2025 16:34
@Sysix Sysix marked this pull request as ready for review November 27, 2025 16:36
@Sysix Sysix force-pushed the 11-25-chore_oxlint_napi_add_createworkspace_destroyworkspace_js_callback_function branch from ce53742 to 8a4ded6 Compare November 27, 2025 16:41
Comment on lines +68 to +70
if let Some(extern_linter) = external_linter {
let _ = (extern_linter.create_workspace)(self.cwd.to_string_lossy().to_string());
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Workspace creation failure is silently ignored. If create_workspace fails, subsequent operations that depend on the workspace (like loadPlugin and lintFile) will fail with cryptic errors.

if let Some(extern_linter) = external_linter {
    (extern_linter.create_workspace)(self.cwd.to_string_lossy().to_string())?;
}

The ? operator should be used to propagate the error, or the error should be logged/handled appropriately.

Suggested change
if let Some(extern_linter) = external_linter {
let _ = (extern_linter.create_workspace)(self.cwd.to_string_lossy().to_string());
}
if let Some(extern_linter) = external_linter {
(extern_linter.create_workspace)(self.cwd.to_string_lossy().to_string())?;
}

Spotted by Graphite Agent

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

}

registeredRules.push(ruleDetails);
registeredRules.get(workspaceDir)?.push(ruleDetails);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Silent failure when pushing rule. If the workspace doesn't exist, the optional chaining causes push to not execute, but no error is thrown. This creates inconsistent state where offset is calculated on line 155 assuming the workspace exists, but the rule is never actually registered.

const rules = registeredRules.get(workspaceDir);
if (!rules) {
  throw new Error(`Workspace "${workspaceDir}" has not been created`);
}
rules.push(ruleDetails);

The workspace should be validated to exist, or an error should be thrown.

Suggested change
registeredRules.get(workspaceDir)?.push(ruleDetails);
const rules = registeredRules.get(workspaceDir);
if (!rules) {
throw new Error(`Workspace "${workspaceDir}" has not been created`);
}
rules.push(ruleDetails);

Spotted by Graphite Agent

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-cli Area - CLI A-editor Area - Editor and Language Server A-linter Area - Linter A-linter-plugins Area - Linter JS plugins C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants